package org.lboot.idmo.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.lboot.core.auth.AuthService;
import org.lboot.core.auth.anno.CheckRole;
import org.lboot.core.domain.ErrMsg;
import org.lboot.core.domain.PageResultDTO;
import org.lboot.core.domain.ResponseDTO;
import org.lboot.core.exception.BusinessException;
import org.lboot.idmo.loader.PasswordGenerator;
import org.lboot.idmo.module.dept.SysDept;
import org.lboot.idmo.module.dept.SysDeptService;
import org.lboot.idmo.module.role.SysRole;
import org.lboot.idmo.module.role.SysRoleService;
import org.lboot.idmo.module.user.SysUser;
import org.lboot.idmo.module.user.SysUserService;
import org.lboot.idmo.module.user.dto.UserDetailVO;
import org.lboot.idmo.module.user.role.SysUserRoleService;
import org.lboot.idmo.module.user.params.UserCreateParams;
import org.lboot.idmo.module.user.params.UserQueryParams;
import org.lboot.idmo.module.user.params.UserUpdateParams;
import org.lboot.idmo.util.RbacUtil;
import org.lboot.jpa.utils.JpaDataUtil;
import org.lboot.llog.anno.ApiLog;
import org.lboot.starter.plugin.rsr.RsrIgnore;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("idm")
@Api(tags = "用户管理")
@AllArgsConstructor
public class IdmoUserController {
    AuthService authService;

    SysUserService userService;

    SysDeptService deptService;

    SysRoleService roleService;

    SysUserRoleService userRoleService;

    PasswordGenerator passwordGenerator;

    private final ThreadPoolTaskExecutor threadExecutor;


    /** 新建用户 **/
    @ApiLog("RBAC")
    @PostMapping("users")
    @ApiOperation(value = "用户新建",notes = "")
    public ResponseDTO<Object> userCreate(@RequestBody @Validated UserCreateParams params)   {
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(params,sysUser, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Optional<SysUser> userOp = userService.getByUsername(params.getUsername());
        if (userOp.isPresent()){
            throw new BusinessException(HttpStatus.BAD_REQUEST, ErrMsg.build("重复账户"));
        }
        // 设置初始密码
        if (Validator.isEmpty(sysUser.getPassword())){
            sysUser.setPassword(passwordGenerator.build());
        }
        // 设置用户类型
        if (Validator.isEmpty(sysUser.getUserType())){
            sysUser.setUserType("普通用户");
        }
        SysUser result = userService.saveOne(sysUser);
        // 部门绑定
        return ResponseDTO.succData(result);
    }


    @ApiLog("RBAC")
    @DeleteMapping("users/{userId}")
    @ApiOperation(value = "用户删除",notes = "")
    @RsrIgnore
    @CheckRole(orPerm = "rbac:user:delete")
    public ResponseDTO<Object> userDelete(@PathVariable("userId") Long userId){
        // 清除关联信息
        userRoleService.deleteByUserId(userId);
        // 清除用户
        userService.deleteOne(userId);
        return ResponseDTO.succMsg("删除成功");
    }

    @ApiLog(value = "RBAC",ignoreResponse = 1)
    @PutMapping("users/{userId}")
    @ApiOperation(value = "用户更新",notes = "")
    public ResponseDTO<Object> userUpdate(@PathVariable("userId") Long userId, @RequestBody @Validated UserUpdateParams params){
        // 既不是管理员也不是自己本人 --
        if (!authService.isAdmin() && !userId.equals(StpUtil.getLoginIdAsLong())){
            return ResponseDTO.wrap(HttpStatus.FORBIDDEN,"权限不足");
        }
        Optional<SysUser> userOp = userService.getOne(userId);
        if (!userOp.isPresent()){
            return ResponseDTO.wrap(HttpStatus.NOT_FOUND);
        }
        SysUser user = userOp.get();
        BeanUtil.copyProperties(params,user,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        SysUser result = userService.updateOne(user);
        return ResponseDTO.succData(RbacUtil.desensitize(result));
    }



    @GetMapping("users")
    @ApiOperation(value = "用户列表",notes = "")
    public ResponseDTO<Object> userListQuery(UserQueryParams params){

        // tips : 页码对应 - 1
        Pageable pageable = JpaDataUtil.buildPageable(params);
        // 如果参数为空
        Specification<SysUser> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            // 构建 pr 模糊 查询
            if (Validator.isNotEmpty(params.getSearchKey())){
                Predicate p1 = cb.like(root.get("nickname"),   params.getSearchKey() + "%");

                Predicate p2 = cb.like(root.get("mobile"),   params.getSearchKey() + "%");

                Predicate p3 = cb.like(root.get("username"),   params.getSearchKey() + "%");

                list.add(cb.or(p1,p2,p3));
            }
            // 基于状态查询
            if (Validator.isNotEmpty(params.getStatus())){
                Predicate p1 = cb.equal(root.get("status"),params.getStatus());
                list.add(p1);
            }
            // 如果部门信息不为空
            if (Validator.isNotEmpty(params.getDeptId())){
                Predicate p2 = cb.equal(root.get("dept"),params.getDeptId());
                list.add(p2);
            }
            // 账户类型
            if (Validator.isNotEmpty(params.getUserType())){
                Predicate p3 = cb.equal(root.get("userType"),params.getUserType());
                list.add(p3);
            }
            Predicate[] predicates = new Predicate[list.size()];
            return cb.and(list.toArray(predicates));
        };
        // 隐藏密码
        PageResultDTO<SysUser> resultDTO =  userService.getAll(pageable,spec);
        List<SysUser> users = resultDTO.getContent();
        users = users.stream().peek(ele-> ele.setPassword("******")).collect(Collectors.toList());
        resultDTO.setContent(users);
        return ResponseDTO.succData(
                resultDTO
        );
    }

    @GetMapping("users/{id}")
    @ApiOperation(value = "用户查询",notes = "")
    public ResponseDTO<Object> userQuery(@PathVariable("id") Long id){
        SysUser user = userService.getOneUnwrap(id);
        return ResponseDTO.succData(RbacUtil.desensitize(user));
    }

    @GetMapping("users/{id}/roles")
    @ApiOperation(value = "用户关联角色")
    public ResponseDTO<Object> userQueryRoles(@PathVariable("id") Long id){
        return ResponseDTO.succData(
                userRoleService.getRoles(id)
        );
    }



    @GetMapping("users/{userId}/password")
    @ApiOperation(value = "获取密码")
    // @CheckRole(orPerm = "user:password:query")
    public ResponseDTO<Object> getPwd(@PathVariable("userId") Long userId){
        // 如果是当前登录用户或者管理员
        SysUser user = userService.getOneUnwrap(userId);
        if (StpUtil.hasRole(userId,"admin")){
            return ResponseDTO.wrap(HttpStatus.FORBIDDEN,"无权操作【admin】");
        }
        return ResponseDTO.succData(
                user.getPassword()
        );
    }

    // 获取用户详细信息
    @GetMapping("user/detail")
    @ApiOperation(value = "获取用户详细信息")
    public ResponseDTO<Object> getUserDetail(){
        if (!StpUtil.isLogin()){
            throw new BusinessException(HttpStatus.UNAUTHORIZED,"未登录");
        }

        // 正常情况下应该是置换
        Long userId = StpUtil.getLoginIdAsLong();
        SysUser user = userService.getOneUnwrap(userId);
        UserDetailVO vo = new UserDetailVO();
        BeanUtil.copyProperties(user, vo, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        // 处理用户ID
        vo.setUserId(user.getId());
        // 获取部门名称
        SysDept dept = deptService.getOneUnwrap(user.getDeptId());
        vo.setDeptName(dept.getDeptName());
        // 获取角色信息
        List<SysRole> roles = userRoleService.getRoles(userId);
        vo.setRoles(roles);
        if (!roles.isEmpty()){
            vo.setCurrentRole(roles.get(0));
        }
        return ResponseDTO.succData(vo);
    }

    @Data
    @ApiModel(value = "密码重置参数")
    public static class PasswordResetParams{
        private String password;
    }

    @PutMapping("users/{userId}/password")
    @ApiOperation(value = "密码重置",notes = "")
    @CheckRole(orPerm = "user:password:reset")
    public ResponseDTO<Object> resetPwd(@PathVariable("userId") Long userId, @Validated @RequestBody PasswordResetParams params){
        SysUser user = userService.getOneUnwrap(userId);
        if (StpUtil.hasRole(userId,"admin")){
            return ResponseDTO.wrap(HttpStatus.FORBIDDEN,ErrMsg.build("无权操作【admin】"));
        }
        user.setPassword(params.getPassword());
        userService.updateOne(user);
        return ResponseDTO.succMsg("重置成功");
    }

}
